package org.xteam.box2text.old;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;


/**
 * G operator is used to group box within a specified operator type.
 * 
 * G gs=2 op=R [ Box1 Box2 Box3 Box4 ] -> R [ Box1 Box2 ] R[ Box3 Box4 ]
 * 
 * @author llhours
 * 6 mai 08
 * $Id$
 */
public class GOperator extends Operator {

	public GOperator(Box...boxes) {
		super(boxes);
	}
	
	public GOperator(List<Box> boxes) {
		super(boxes);
	}

	public GOperator(Map<String, Integer> options, List<Box> arguments) {
		super(options, arguments);
	}

	public List<Box> normalizeGroups(boolean splice) {
		List<Box> children = normalizeChildren(false);
		if (! options.containsKey("op")) {
			if (splice)
				return children;
			// we are inside an other G operator: recreate the G box
			return Arrays.asList(new Box[] { this }); 
		}
		int op = options.get("op");
		int gs = options.get("gs");
		List<Box> results = new ArrayList<Box>();
		int index = 0;
		int nGroup = (children.size()+gs-1)/gs;
		for (int i = 0; i < nGroup; ++i) {
			List<Box> args = null;
			if (index + gs >= children.size()) {
				args = subList(children, index, children.size());
				// complete the group with empty H operators
				for (int j = args.size(); j < gs; ++j) {
					args.add(new HOperator());
				}
			} else {
				args = subList(children, index, index+gs);
			}
			results.add(makeOp(op, args));
			index += gs;
		}
		if (splice) {
			List<Box> res = new ArrayList<Box>();
			for (Box box : results) {
				res.addAll(box.normalizeGroups(true));
			}
			return res;
		}
		// build a G operator without op attribute
		return Arrays.asList(new Box[] { new GOperator(children) });
	}

	private static List<Box> subList(List<Box> list, int start, int end) {
		List<Box> result = new ArrayList<Box>();
		for (int i = start; i < end; ++i) {
			result.add(list.get(i));
		}
		return result;
	}

	private static Box makeOp(int op, List<Box> arguments) {
		if (op == OperatorKinds.R)
			return new ROperator(arguments);
		throw new RuntimeException("makeOp: not completed");
	}

}
